package drds.plus.executor.row_values.row_value;

import drds.plus.executor.cursor.cursor_metadata.CursorMetaData;
import drds.plus.executor.row_values.RowValues;
import drds.plus.sql_process.abstract_syntax_tree.expression.item.Item;
import drds.plus.sql_process.abstract_syntax_tree.expression.order_by.OrderBy;
import drds.plus.sql_process.type.Type;
import drds.plus.sql_process.type.Types;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;

public class RowValueScaners {
    /**
     * 这个是针对相同排序列的一个游标进行处理
     * <p>
     * 根据order by 条件，从left和right KVPair里面拿到一个列所对应的值(从key或者从value里面） 然后进行比较。
     * 相等则继续比较其他。 不相等则根据asc desc决定大小。
     */
    public static Comparator<RowValues> getRowDataComparator(final CursorMetaData cursorMetaData, final List<OrderBy> orderByList) {
        return new Comparator<RowValues>() {

            public IRowValueScaner leftSideRowDataValueScaner;
            public IRowValueScaner rightSideRowDataValueScaner;
            public List<Item> itemList;

            {
                itemList = new ArrayList<Item>();
                for (OrderBy orderBy : orderByList) {
                    itemList.add(orderBy.getItem());
                }
                leftSideRowDataValueScaner = new RowValueScanerImpl(cursorMetaData, itemList);
            }

            public int compare(RowValues leftSideRowData, RowValues rightSideRowData) {
                if (rightSideRowDataValueScaner == null) {
                    CursorMetaData rightCursorMeta = rightSideRowData.getParentCursorMetaData();
                    rightSideRowDataValueScaner = new RowValueScanerImpl(rightCursorMeta, itemList);
                }
                Iterator<Object> leftSideRowDataValueIterator = leftSideRowDataValueScaner.rowDataValueIterator(leftSideRowData);
                Iterator<Object> rightSideRowDataValueIterator = rightSideRowDataValueScaner.rowDataValueIterator(rightSideRowData);
                for (OrderBy orderBy : orderByList) {
                    Object leftRowValue = leftSideRowDataValueIterator.next();
                    Object rightRowValue = rightSideRowDataValueIterator.next();

                    if (leftRowValue == null && rightRowValue == null) {
                        continue;
                    }
                    int result = RowValueScaners.compare(leftRowValue, rightRowValue, orderBy);
                    if (result == 0) {
                        continue;
                    }
                    return result;// 一个字段不等则退出,否则等到所有的字段都比较完
                }
                return 0;
            }
        };

    }

    /**
     * 这个是针对可能相同排序列的两个游标进行处理
     */
    public static Comparator<RowValues> getComparator(final CursorMetaData leftCursorMetaData, final List<Item> leftSideItemList, final CursorMetaData rightCursorMetaData, final List<Item> rightSideItemList) {
        return new Comparator<RowValues>() {

            public IRowValueScaner leftSideRowsValueScaner = new RowValueScanerImpl(leftCursorMetaData, leftSideItemList);
            public IRowValueScaner rightSideRowsValueScaner = new RowValueScanerImpl(rightCursorMetaData, rightSideItemList);

            public int compare(RowValues o1, RowValues o2) {
                Iterator<Object> leftSideRowDataValueIterator = leftSideRowsValueScaner.rowDataValueIterator(o1);
                Iterator<Object> rightSideRowDataValueIterator = rightSideRowsValueScaner.rowDataValueIterator(o2);
                for (int i = 0; i < leftSideItemList.size(); i++) {
                    Object c1 = leftSideRowDataValueIterator.next();
                    Object c2 = rightSideRowDataValueIterator.next();
                    int n = RowValueScaners.compare(c1, leftSideItemList.get(i).getType(), c2, rightSideItemList.get(i).getType());
                    if (n != 0) {
                        return n;
                    }
                }
                return 0;
            }
        };
    }

    public static int compare(Object c1, Type type1, Object c2, Type type2) {
        if (type1 == null) {
            type1 = Types.getTypeOfObject(c1);
        }
        // 类型相同，直接比较
        if (type1 == type2) {
            return type1.compare(c1, c2);
        }
        // 类型不同，先进行类型转换
        c2 = type1.convert(c2);
        return type1.compare(c1, c2);
    }

    public static int compare(Object leftObject, Object rightObject, OrderBy orderBy) {
        Type type = orderBy.getItem().getType();
        if (type == null) {
            type = Types.getTypeOfObject(leftObject);
        }
        int result = type.compare(leftObject, rightObject);
        if (result == 0) {
            return result;
        }
        boolean isAsc = orderBy.getAsc();
        if (isAsc) {
            return result;
        } else {
            return result < 0 ? 1 : -1;
        }
    }
}
